#!/usr/bin/env bash
#

# path to lua-cross-compiler
DIR=`realpath $0`
DIR=`dirname $DIR`

CC=@CROSS_TRIPLE@-gcc
LLVM_LUAC="./@CROSS_TRIPLE@-llvm-luac"

# find llvm-luac cross-compiler
if [[ ! -x "$LLVM_LUAC" ]]; then
	LLVM_LUAC="$DIR/@CROSS_TRIPLE@-llvm-luac"
fi
if [[ ! -x "$LLVM_LUAC" ]]; then
	LLVM_LUAC=`which @CROSS_TRIPLE@-llvm-luac`
fi

ARCH=@CROSS_ARCH@
CPU=@CROSS_CPU@
FORCE_CPU="0"
MODULE="0"
NO_ASSEMBLE="0"
FILE=lua-native-out
FILES=""
DEBUG="0"
KEEP_TMPS="0"
EXTRA_ARGS=

function echo_cmd() {
	CMD="$1"
	shift 1
	echo "$CMD" "$@"
	$CMD "$@"
}

function version() {
	$LLVM_LUAC -version
	exit 0;
}

function usage() {
	echo "USAGE: $0 [options] <script>

OPTIONS:
  -lua-module      - Compile Lua script into a loadable module instead of a standalone
                       executable.
  -no-assemble     - Only compile to native Assembly code or C-code, don't compile to machine code.
  -debug           - Turns off all optimizations and turns on debug info.  Both Lua debug
                       info and gcc debug symbols are enabled.
  -keep-tmps       - Don't delete temp. files generated by intermediate stages.  Use only
                       for debuging generated code or if you are really curious!
  -march=<march>   - <march> is passed to llc as '-march=<march>', see llc --version for targets
  -mcpu=<arch>     - <cpu> is passed to gcc as '-march=<cpu>'
  -******          - All other options passed to 'llvm-luac'.  See below for a list of
                       options supported by 'llvm-luac'.

llvm-luac '-help' output:
"
	$LLVM_LUAC -help
	exit 0;
}

# parse command line parameters.
CONSUME=""
for arg in "$@" ; do
	case "$CONSUME" in
	-o)  OUTPUT_FILE=` echo "$arg" | sed -e 's/-o=//'` ;;
	-L)  EXTRA_ARGS="$EXTRA_ARGS -L $arg" ;;
	esac
	if [[ ! -z "$CONSUME" ]]; then
		CONSUME=""
		continue
	fi
	case "$arg" in
	-lua-mod*)  MODULE="1"; EXTRA_ARGS="$EXTRA_ARGS $arg" ;;
	-debug)  DEBUG="1" ;;
	-no-assemble)  NO_ASSEMBLE="1" ;;
	-keep-tmps)  KEEP_TMPS="1" ;;
	-march=*)  ARCH=` echo "$arg" | sed -e 's/-march=//'` ;;
	-mcpu=*)  FORCE_CPU="1"; CPU=` echo "$arg" | sed -e 's/-mcpu=//'` ;;
	-help|--help|-h)  usage ;;
	-version|--version|-v)  version ;;
	-o|-L)  CONSUME="$arg" ;;
	-L*)  EXTRA_ARGS="$EXTRA_ARGS $arg" ;;
	-*)  EXTRA_ARGS="$EXTRA_ARGS $arg" ;;
	*) FILE=${arg/.lua/}; FILES="$FILES $arg" ;;
	esac
done

# find the mode's output file extension.
OUTPUT_EXT=""
MODE_OUT=""
OUTPUT_EXT=".s"
if [[ -z "$OUTPUT_FILE" ]]; then
	if [[ $MODULE == "0" && $NO_ASSEMBLE == "0" ]]; then
		OUTPUT_FILE="${FILE}"
	else
		OUTPUT_FILE="${FILE}${OUTPUT_EXT}"
	fi
else
	FILE=${OUTPUT_FILE}
fi
MODE_OUT="${FILE}${OUTPUT_EXT}"

# select debug/optimize parameters.
if [[ $DEBUG == "1" ]]; then
	LUA_FLAGS=" -O0 -g "
	LLC_FLAGS=" -O0 "
else
	LUA_FLAGS=" -O3 -s "
	LLC_FLAGS=" -O3 -tailcallopt "
fi
if [[ ! -z "$CPU" ]]; then
	LLC_FLAGS=" -mcpu=$CPU $LLC_FLAGS "
fi
if [[ ! -z $ARCH ]]; then
	LLC_FLAGS=" -march=$ARCH $LLC_FLAGS "
fi

#
# run llvm-luac to compile Lua source/bytecode to LLVM bitcode.
#
echo_cmd $LLVM_LUAC $EXTRA_ARGS $LUA_FLAGS -bc -o ${FILE}.bc ${FILES} || {
	echo "llvm-luac: failed to compile Lua code into LLVM bitcode."
	exit 1;
}
TMPS="${FILE}.bc"
echo_cmd llc $LLC_FLAGS -filetype=asm -o ${MODE_OUT} ${FILE}.bc

# compile to stand-alone
if [[ $MODULE == "0" && $NO_ASSEMBLE == "0" ]]; then
	echo_cmd ${CC} -o ${OUTPUT_FILE} ${MODE_OUT} -lm -ldl && \
	TMPS="$TMPS ${MODE_OUT}"
fi

# keep assembly/c-code output.
if [[ $NO_ASSEMBLE == "1" && $MODE_OUT != $OUTPUT_FILE ]]; then
	echo_cmd mv $MODE_OUT $OUTPUT_FILE
fi

if [[ $KEEP_TMPS == "0" ]]; then
	rm -f $TMPS
fi

